﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace AutoNotify
{

    public static class TimerHolder
    {

        /// <summary>
        /// 托管的所有form及其Timers
        /// </summary>
        static List<FormTimersHolder> g_formsList = new List<FormTimersHolder>();

        /// <summary>
        /// 清除该窗体下的所有Timer
        /// </summary>
        /// <param name="f"></param>
        public static void ClearAllReaptingTimer(this Form f)
        {
            FindFormTimersHolder(f).timersList.Clear();
        }

        /// <summary>
        /// 清除这个Form下的对应Timer，并停止其工作
        /// </summary>
        public static void ClearReatingTimer(this Form form, int timerHashCode)
        {
            FormTimersHolder holder = FindFormTimersHolder(form);
            
            int timerIndex= holder.FindTimerIndex(timerHashCode);

            //说明这个code是错的或者已经删除过了：
            if (timerIndex < 0)
                return;

            Timer timer = holder.timersList[timerIndex];

            //--删除之
            holder.timersList.RemoveAt(timerIndex);
            
            //这个Timer应该拜拜了。
            timer.Stop();
            timer.Enabled = false;
            timer.Dispose();
        }

        /// <summary>
        /// 暂停一个Timer
        /// </summary>
        public static void StopReatingTimer(this Form form, int timerHashCode)
        {
            Timer timer = FindTimerAtForm(form, timerHashCode);
            
            if(timer != null )
                timer.Stop();
        }

        /// <summary>
        /// 重新启动一个Timer
        /// </summary>
        public static void RestartReaptingTimer(this Form form, int timerHashCode)
        {
            Timer timer = FindTimerAtForm(form, timerHashCode);

            if (timer != null )
                timer.Start();
        }

        /// <summary>
        /// 启动一个计时器：用于重复地执行某件事，间隔N毫秒；并返回计时器hashCode
        /// </summary>
        /// <remarks>拓展Form的行为</remarks>
        public static int InvokeRepeating(this Form f, CallbackFunc cb,int miliseconds)
        {
            //找到对应的管理列表
            FormTimersHolder formTimers = FindFormTimersHolder(f);
            
            //没找到时，自动生成一个Form管理器
            if(formTimers == null)
            {
                formTimers = new FormTimersHolder(f);
                g_formsList.Add(formTimers);
            }
        
            
            //生成一个新的timer
            Timer timer = new Timer();
            
            //增加到管理列表中：
            formTimers.timersList.Add(timer);

            //timmer的事件设置
            timer.Enabled = true;
            timer.Interval = miliseconds;
            timer.Tick += new EventHandler((obj, eventArgs) => { cb(); });

            //启动计时器
            timer.Start();

            //返回timer的对应id
            int timerID = timer.GetHashCode();

            return timerID;
        }


        /// <summary>
        /// 设置一个延迟N毫秒的动作
        /// </summary>
        public static void SetTimeout(this Form form , CallbackFunc cbFunc, int delayMiliseconds)
        {
            int hashCode = -1;

            //设置一个定时器：
            hashCode = InvokeRepeating(form, () =>
            {
                //--销毁这个定时器
                ClearReatingTimer(form, hashCode);
             
                //--执行回调动作：
                cbFunc();

            }, 
            delayMiliseconds);
        }

        //---------------------------------------------------------------------------
        //                      私有类及方法
        //---------------------------------------------------------------------------
        
        /// <summary>
        /// 窗口Timer的结构体，用于管理该窗体下的所有Timers
        /// </summary>
        class FormTimersHolder 
        {
            /// <summary>
            /// 窗体
            /// </summary>
            public Form form{get;private set;}

            /// <summary>
            /// 该窗体下的所有timer托管
            /// </summary>
            public List<Timer> timersList{get;private set;}

            public FormTimersHolder(Form form)
            {
                this.form = form;
                timersList = new List<Timer>();
            }

            
            /// <summary>
            /// 从列表中找到对应的Timer的位置
            /// </summary>
            public int FindTimerIndex(int timerHashCode)
            {
                int indexFound = -1;
                for (int i= 0; i < timersList.Count; i++)
                {
                    if (timersList[i].GetHashCode() == timerHashCode)
                    {
                        indexFound = i;
                        break;
                    }
                }

                return indexFound;
            }

            public Timer FindTimer(int timerHashCode)
            {
                int id = FindTimerIndex(timerHashCode);
                if (id < 0)
                {
                    return null;
                }
                else
                { 
                    return timersList[id]; 
                }
            }
        }

        /// <summary>
        /// 找到form中对应的Timer
        /// </summary>
        private static Timer FindTimerAtForm(Form form, int timerHashCode)
        {
            FormTimersHolder holder = FindFormTimersHolder(form);

            if (holder != null)
            {
                Timer timer = holder.FindTimer(timerHashCode);

                return timer;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 从列表中找到对应的form
        /// </summary>
        private static FormTimersHolder FindFormTimersHolder(Form fToFind)
        {
            //直接find
            //FormTimers result = g_formsList.Find(new Predicate<FormTimers>((target) => { return fToFind == target.form; }));
            
            //自己老老实实查找：
            for (int i = 0; i < g_formsList.Count; i++)
            {
                if (g_formsList[i].form == fToFind)
                {
                    return g_formsList[i];
                }
            }
            
            return null;
            
        }


    }
}
